package top.superflow.flow.config.parse.center

import org.apache.commons.lang3.builder.ToStringBuilder
import top.superflow.exception.{Exceptable, RequestUnsupportedException}
import top.superflow.flow.config.parse.Parser
import top.superflow.flow.config.parse.impl.{MapperConfigParser, ProcessConfigParser, ProcessProviderConfigParser, ResourceConfigParser}
import top.superflow.flow.config.process.ProcessConfig
import top.superflow.flow.config.process.provider.ProcessProviderConfig
import top.superflow.flow.config.{Config, Identifiable, ResourceConfig}
import top.superflow.flow.mapper.MapperConfig
import top.superflow.lang.StringUtils
import top.superflow.log.Loggable

class GlobalParserCenter private() extends Loggable with Exceptable{

  def init(dependencies : Map[String, Any]): Unit ={
    ParserLoader.getInstance.init(dependencies)
    ParserLoader.getInstance.load
  }


  def register(configParserKey : String, parser : Parser[_ <: Identifiable] ): Unit ={
    if(parser == null){
      throw new UnsupportedOperationException("parser should not be null when registering parser")
    }

    validate(configParserKey)

    parser match {
      case processParser : ProcessConfigParser => {
        ProcessConfigParserCenter.getInstance.register(configParserKey, processParser)
      }
      case processProviderConfigParser : ProcessProviderConfigParser => {
        ProcessProviderConfigParserCenter.getInstance.register(configParserKey, processProviderConfigParser)
      }
      case resourceConfigParser : ResourceConfigParser => {
        ResourceConfigParserCenter.getInstance.register(configParserKey, resourceConfigParser)
      }
      case mapperConfigParser : MapperConfigParser => {
        MapperConfigParserCenter.getInstance.register(configParserKey, mapperConfigParser)
      }
      case _ => {
        throwRequestUnsupportedException("The the parser can't be identified [{}]", ToStringBuilder.reflectionToString(parser))
      }
    }
  }

  private def validate(configParserKey : String): Unit ={
    if(StringUtils.isBlank(configParserKey)){
      throwRequestUnsupportedException("The key of the parser should not be null!")
    }

    if(ProcessConfigParserCenter.getInstance.contains(configParserKey)){
      throwRequestUnsupportedException("There is already process config parser named as {}" , configParserKey)
    }

    if(ProcessProviderConfigParserCenter.getInstance.contains(configParserKey)){
      throwRequestUnsupportedException("There is already process provider config parser named as {}" , configParserKey)
    }

    if(ResourceConfigParserCenter.getInstance.contains(configParserKey)){
      throwRequestUnsupportedException("There is already resource config parser named as {}" , configParserKey)
    }

    if(MapperConfigParserCenter.getInstance.contains(configParserKey)){
      throwRequestUnsupportedException("There is already mapper config parser named as {}" , configParserKey)
    }
  }

  def getParser[_]( config : Config) : Parser[_] = {

    if(config == null){
      throwRequestUnsupportedException("The config should not be null")
    }

    config match {
      case processConfig : ProcessConfig => {
        val processType = processConfig.getProcessType
        if(StringUtils.isBlank(processType)){
          throwRequestUnsupportedException("The processType of the proccess configuration [{}] is required!", processConfig.getKey)
        }
        ProcessConfigParserCenter.getInstance.getParser(processConfig.getProcessType)
      }

      case processProviderConfig : ProcessProviderConfig => {
        val providerType = processProviderConfig.getProviderType
        if(StringUtils.isBlank(providerType)){
          throwRequestUnsupportedException("The providerType of the proccess provier configuration [{}] is required!", processProviderConfig.getKey)
        }
        ProcessProviderConfigParserCenter.getInstance.getParser(processProviderConfig.getProviderType)
      }
      case resourceConfig : ResourceConfig => {
        ResourceConfigParserCenter.getInstance.getParser(resourceConfig.getResourceType)
      }
      case mapperConfig : MapperConfig => {
        MapperConfigParserCenter.getInstance.getParser(mapperConfig.getMapperType)
      }
      case _ => {
        throw new RequestUnsupportedException("The the config can't be identified [" + ToStringBuilder.reflectionToString(config) + "]")
      }
    }

  }


}

object GlobalParserCenter{
  private final val instance = new GlobalParserCenter

  def getInstance = instance
}
